# coding=utf-8
import re
import sys

"""
我的包
"""


class MyValidator:
    """
    验证器
    """

    @classmethod
    def is_integer(cls, param, language='zh'):
        """
        大于等于零的整数
        @param param:
        @param language:
        @return: bool
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, int):
            return False, message

        pattern = re.compile(r'^(0|[1-9][0-9]*)$')
        if pattern.match(str(param)) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def is_float(cls, param, language='zh'):
        """
        正浮点数
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, float):
            return False, message
        pattern = re.compile(r'^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$')
        if pattern.match(str(param)) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def numeric(cls, param, language='zh'):
        """
        验证字段必须为 数值(正负整数，正负浮点数)。
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if isinstance(param, int) or isinstance(param, float):
            return True, MyValidatorLanguage.get_success(language=language)
        else:
            return False, message

    @classmethod
    def alpha(cls, param, language='zh'):
        """
        字母
        @param param:
        @param language:
        @return: bool
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[A-Za-z]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def alpha_dash(cls, param, language='zh'):
        """
        字母、数字，短破折号（-）和下划线（_）
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[\w|-]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def alpha_num(cls, param, language='zh'):
        """
        字母、数字
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[A-Za-z0-9]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def is_cn(cls, param, language='zh'):
        """
        汉字
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[\u4e00-\u9fa5]{0,}$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def ch_alpha(cls, param, language='zh'):
        """
        汉字、字母、下划线、破折号
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[\u4E00-\u9FA5A-Za-z_-]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def ch_alpha_num(cls, param, language='zh'):
        """
        汉字、字母、数字、下划线、破折号
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[\u4E00-\u9FA5A-Za-z0-9_-]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def is_lower(cls, param, language='zh'):
        """
        小写字母
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[a-z]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def is_upper(cls, param, language='zh'):
        """
        大写字母
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[A-Z]+$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def between(cls, param, n, m, language='zh'):
        """
        验证字段的长度必须在给定的 min 和 max 之间
        @param param:
        @param n:
        @param m:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, m, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if n <= len(str(param)) <= m:
                return True, MyValidatorLanguage.get_success(language=language)
        elif n <= len(param) <= m:
            return True, MyValidatorLanguage.get_success(language=language)
        else:
            return False, message

    @classmethod
    def boolean(cls, param, language='zh'):
        """
        验证的字段必须可以转换为 Boolean 类型。 可接受的输入为 true, false, 1, 0, "1", 和 "0"。
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if isinstance(param, bool):
            return True, MyValidatorLanguage.get_success(language=language)
        elif param in [0, 1]:
            return True, MyValidatorLanguage.get_success(language=language)
        elif param in ['0', '1']:
            return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def digits(cls, param, n, language='zh'):
        """
        值 param 长度等于 n
        @param param:
        @param n:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, language=language)
        if isinstance(param, float) or isinstance(param, int):
            if len(str(param)) == n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif len(param) == n:
            return True, MyValidatorLanguage.get_success(language=language)
        else:
            return False, message

    @classmethod
    def digits_between(cls, param, n, m, language='zh'):
        """
        int|float 的值在 n ~ m 之间
        @param param:
        @param n:
        @param m:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, m, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if n <= param <= m:
                return True, MyValidatorLanguage.get_success(language=language)
        else:
            return False, message
        return False, message

    @classmethod
    def email(cls, param, language='zh'):
        """
        验证的字段必须符合 e-mail 地址格式
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def gt(cls, param, n, language='zh'):
        """
        比较形式：大于
        比较整型、浮点大小
        比较字符串、字典、列表长度
        @param param:
        @param n:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if param > n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, str):
            if len(param) > n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, dict) or isinstance(param, list) or isinstance(param, tuple):
            if len(param) > n:
                return True, MyValidatorLanguage.get_success(language=language)
        else:
            if len(param) > n:
                return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def gte(cls, param, n, language='zh'):
        """
        比较形式：大于等于
        比较整型、浮点大小
        比较字符串、字典、列表长度
        @param param:
        @param n:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if param >= n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, str):
            if len(param) >= n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, dict) or isinstance(param, list) or isinstance(param, tuple):
            if len(param) >= n:
                return True, MyValidatorLanguage.get_success(language=language)
        else:
            if len(param) >= n:
                return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def lt(cls, param, n, language='zh'):
        """
        比较形式：小于
        比较整型、浮点大小
        比较字符串、字典、列表长度
        @param param:
        @param n:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if param < n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, str):
            if len(param) < n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, dict) or isinstance(param, list) or isinstance(param, tuple):
            if len(param) < n:
                return True, MyValidatorLanguage.get_success(language=language)
        else:
            if len(param) < n:
                return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def lte(cls, param, n, language='zh'):
        """
        比较形式：小于等于
        比较整型、浮点大小
        比较字符串、字典、列表长度
        @param param:
        @param n:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, n, language=language)
        if isinstance(param, int) or isinstance(param, float):
            if param <= n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, str):
            if len(param) <= n:
                return True, MyValidatorLanguage.get_success(language=language)
        elif isinstance(param, dict) or isinstance(param, list) or isinstance(param, tuple):
            if len(param) <= n:
                return True, MyValidatorLanguage.get_success(language=language)
        else:
            if len(param) <= n:
                return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def ipv4(cls, param, language='zh'):
        """
        验证的字段必须是 IPv4 地址。
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}')
        if pattern.match(param) is None:
            return False, message
        return True, MyValidatorLanguage.get_success(language=language)

    @classmethod
    def website(cls, param, language='zh'):
        """
        网址, http://www.baidu.com, www.baidu.com
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?')
        if pattern.match(param) is None:
            return False, message
        return True,MyValidatorLanguage.get_success(language=language)

    @classmethod
    def uri(cls, param, language='zh'):
        """
        uri, /admin/user/index, admin/user/index
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if not isinstance(param, str):
            return False, message
        pattern = re.compile(r'^[A-Za-z0-9-|/|_]+$')
        if pattern.match(param) is None:
            return False, message
        return True,MyValidatorLanguage.get_success(language=language)

    @classmethod
    def required(cls, param, language='zh'):
        """
        验证中的字段必须存在于输入数据中，并且不能为空。
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if param is None or 1 > len(param):
            return True, MyValidatorLanguage.get_success(language=language)
        return False, message

    @classmethod
    def phone_number(cls, param, language='zh'):
        """
        中国手机号码
        @param param:
        @param language:
        @return:
        """
        validate = sys._getframe().f_code.co_name
        message = MyValidatorLanguage.get_message(validate, language=language)
        if isinstance(param, str) or isinstance(param, int):
            pattern = re.compile(r'^(1[3-9][0-9])\d{8}$')
            if pattern.match(str(param)) is None:
                return False, message
            return True, MyValidatorLanguage.get_success(language=language)
        return False, message


class MyValidatorLanguage:
    """
    验证器-语言
    """
    __language = {
        'zh': 'zh',
        'en': 'en'
    }

    __messages = {
        'success': {'zh': '成功'},
        'failed': {'zh': '失败'},
        'is_integer': {'zh': '仅支持大于等于零的整数'},
        'is_float': {'zh': '仅支持大于等于零的小数'},
        'numeric': {'zh': '仅支持数字'},
        'alpha': {'zh': '仅支持字母'},
        'alpha_dash': {'zh': '仅支持字母、数字、短破折号（-）、下划线（_）'},
        'alpha_num': {'zh': '仅支持字母、数字'},
        'is_cn': {'zh': '仅支持汉字'},
        'ch_alpha': {'zh': '仅支持汉字、字母、下划线、破折号'},
        'ch_alpha_num': {'zh': '仅支持汉字、字母、数字、短破折号（-）、下划线（_）'},
        'is_lower': {'zh': '仅支持小写字母'},
        'is_upper': {'zh': '仅支持大写字母'},
        'between': {'zh': '仅支持长度在 {0} 和 {1} 之间的字符'},
        'boolean': {'zh': '仅支持 true、false、1、0、"1"、"0"'},
        'digits': {'zh': '仅支持长度等于 {0} 的字符'},
        'digits_between': {'zh': '仅支持 {0} ~ {1} 的数字'},
        'email': {'zh': '仅支持邮件地址'},
        'gt': {'zh': '仅支持长度大于 {0} 的字符'},
        'gte': {'zh': '仅支持长度大于等于 {0} 的字符'},
        'lt': {'zh': '仅支持长度小于 {0} 的字符'},
        'lte': {'zh': '仅支持长度小于等于 {0} 的字符'},
        'ipv4': {'zh': '仅支持 IP 地址'},
        'required': {'zh': '此为必填项'},
        'phone_number': {'zh': '仅支持手机号码'},
        'website': {'zh': '仅支持网址'},
        'uri': {'zh': '仅支持 uri:"admin/user/index" 地址'},
    }

    @classmethod
    def get_message(cls, validate, *args, language='zh'):
        if validate == 'between' or validate == 'digits_between':
            n, m = args
            return cls.__messages[validate][language].format(n, m)
        elif validate == 'digits':
            n = args
            return cls.__messages[validate][language].format(n)
        elif validate == 'gt' or validate == 'gte' or validate == 'lt' or validate == 'lte':
            n = args
            return cls.__messages[validate][language].format(n)

        return cls.__messages[validate][language]

    @classmethod
    def get_success(cls, language='zh'):
        return cls.__messages['success'][language]

    @classmethod
    def get_failed(cls, language='zh'):
        return cls.__messages['failed'][language]

